package com.ljf.framework.schedule;

import com.ljf.framework.Async.AsyncEvent;
import com.ljf.framework.Async.AsyncManager;
import com.ljf.framework.log.LjfLogManager;
import com.ljf.framework.log.LjfLogService;
import com.ljf.framework.util.ObjectUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.*;

/**
 * 说明：
 *
 * @Auther: lijinfeng
 * @Date: 2025/1/9
 */
public class LjfScheduleManager {

    private static final LjfLogService log = LjfLogManager.getLogger(LjfScheduleManager.class);

    private static ThreadPoolExecutor executor;

    private static volatile HashMap<String, LjfScheduleTask> taskHashMap = new HashMap<>(200);

    public ArrayList<LjfScheduleTask> getTaskList() {
        ArrayList<LjfScheduleTask> taskList = new ArrayList<>();
        taskHashMap.forEach( (k,v) -> {
            taskList.add(v);
        });
        return taskList;
    }

    public void deleteTask(String taskId) {
        taskHashMap.get(taskId).setLjfTaskEnum(LjfTaskEnum.delete);
        taskHashMap.remove(taskId);
    }

    public void stopTask(String taskId) {
        taskHashMap.get(taskId).setLjfTaskEnum(LjfTaskEnum.stop);
    }


    private static synchronized HashMap<String, LjfScheduleTask> addTask(LjfScheduleTask ljfScheduleTask) {
        LjfScheduleTask oldJobThread = taskHashMap.get(ljfScheduleTask.getTaskId());
        if (!ObjectUtil.isEmpty(oldJobThread)) {
            ljfScheduleTask.setLjfTaskEnum(LjfTaskEnum.delete);
        }
        taskHashMap.put(ljfScheduleTask.getTaskId(), ljfScheduleTask);
        return taskHashMap;
    }

    public static synchronized HashMap<String, LjfScheduleTask> removeTask(LjfScheduleTask ljfScheduleTask) {
        ljfScheduleTask.setLjfTaskEnum(LjfTaskEnum.delete);
        taskHashMap.remove(ljfScheduleTask.getTaskId());
        return taskHashMap;
    }

    public static void start() {
        executor = new ThreadPoolExecutor(
                10,
                200,
                60L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(2000),
                new ThreadFactory() {
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r, "ljf-Task, LjfScheduleManager executor-" + r.hashCode());
                    }
                },
                new RejectedExecutionHandler() {
                    @Override
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                        throw new RuntimeException("ljf-Task, LjfScheduleManager executor is EXHAUSTED!");
                    }
                });
    }

    public static void shutdown() {
        executor.shutdown();// 此方法会停止接受新任务，但不会中断已经提交的任务
        log.info("LjfScheduleManager开始关闭调度任务");
        try {
            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); // 等待所有任务执行完毕
        } catch (InterruptedException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt(); // 重新中断当前线程
        }
        log.info("所有任务执行完毕,LjfSchedule关闭完成");
    }
    public static void executeAsync(LjfScheduleTask ljfScheduleTask, Date startDate, Date endDate, String corn) {
        AsyncManager.runAsync(new AsyncEvent<Void>(){
            @Override
            public Void run() {
                execute(ljfScheduleTask,startDate,endDate,corn);
                return null;
            }
        });
    }

    public static void execute(LjfScheduleTask ljfScheduleTask, Date startDate, Date endDate, String corn) {
        addTask(ljfScheduleTask);
        if (executor.isShutdown()) {
            return;
        }

        // 等待开始
        Date runDate = new Date();
        // 如果当前时间在开始时间之前，则睡到开始时间再实行，如果是之后则立即开始执行任务
        if (startDate != null && runDate.before(startDate)) {
            long delay = startDate.getTime() - runDate.getTime();
            try {
                Thread.sleep(delay);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
            runDate = new Date();
        }

        try {
            ljfScheduleTask.run();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
//        executor.execute(new Runnable() {
//            @Override
//            public void run() {
//                try {
//                    log.debug("ljf-Task:" + ljfScheduleTask.getTaskId() + " 开始执行");
//                    ljfScheduleTask.run();
//                    log.debug("ljf-Task:" + ljfScheduleTask.getTaskId() + " 执行完毕");
//                } catch (Exception e) {
//                    throw new RuntimeException(e);
//                }
//            }
//        });

        // 没有运行计划则只执行一次
        if (ObjectUtil.isEmpty(corn))
            return;


        LjfTaskEnum ljfTaskEnum = ljfScheduleTask.getLjfTaskEnum();
        // 任务被停止则退出
        if (ljfTaskEnum == LjfTaskEnum.stop)
            return;

        // 等待运行完成
        while (!(ljfTaskEnum == LjfTaskEnum.completed)) {
            ljfTaskEnum = ljfScheduleTask.getLjfTaskEnum();
        }

        // 到截止时间则退出
        if (endDate != null && new Date().after(endDate)) {
            return;
        }

        // 下次执行时间超过停止时间则退出
        CronParser cronParser = new CronParser(corn);
        Date nextRunDate = cronParser.nextDate(runDate);
        log.debug("ljf-Task:" + ljfScheduleTask.getTaskId()+nextRunDate);
        if (endDate != null && nextRunDate.after(endDate)) {
            return;
        }
        // 执行下一次
        ljfScheduleTask.setLjfTaskEnum(LjfTaskEnum.init);
        execute(ljfScheduleTask, nextRunDate, endDate, corn);
    }




}
